package abel.wlmr.model.type;

import java.util.Collections;
import java.util.HashMap;
import java.util.Map;

import abel.wlmr.model.WlmrException;
import abel.wlmr.model.WlmrField;

/**
 * Default to - 0011 1110, 1.0m3/h.
 * 
 * 0011 1nnn 体积流量 10（nnn-6)m3/h 0.001 l/h ～ 10 000 l/h
 * 0100 0nnn 体积流量 10（nnn-7)m3/h 0.000 1 l/min ～ 1 000 l/min
 * 0100 1nnn 体积流量 10（nnn-9)m3/h 0.001 ml/s ～ 10 000 ml/s
 * 0101 0nnn 质量流量 10（nnn-3)kg/h 0.001 kg/h ～ 10 000 kg/h
 * 
 * [0,7]. 10**n mL/h, [0.001L, 10000L].
 * 
 * @author Abel
 */
public class FlowUnitField extends WlmrField {

    public static final byte PREFIX_LITRE = 0x38;
    public static final byte PREFIX_1T_LITRE = 0x40;
    public static final byte PREFIX_1K_LITRE = 0x41;
    public static final byte PREFIX_1KG = 0x50;

    /**
     * base unit indicator.
     * 0x38 - 10(nnn-6) m3/h
     * 0x40 - 10(nnn-7) m3/h
     * 0x41 - 10(nnn-9) m3/h
     * 0x50 - 10(nnn-3) kg/h
     */
    private byte prefix = PREFIX_LITRE;

    public static final Map<Byte, Integer> velocityMap;

    /** [0,7]. 10**n mL/h, [0.001L, 10000L]. */
    private byte nn = 6;

    static {
        Map<Byte, Integer> map = new HashMap<>();
        map.put((byte) PREFIX_LITRE, 6);
        map.put((byte) PREFIX_1T_LITRE, 7);
        map.put((byte) PREFIX_1K_LITRE, 9);
        map.put((byte) PREFIX_1KG, 3);

        velocityMap = Collections.unmodifiableMap(map);
    }

    public FlowUnitField() {
        super(1);
    }

    @Override
    public int getValue() {
        return prefix | nn;
    }

    @Override
    public void parseValue(int v) throws WlmrException {
        byte key = (byte) (v & 0xF8);

        if (!velocityMap.containsKey(key)) {
            throw new WlmrException("flow unit prefix is invalid: 0x" + Integer.toHexString(key));
        }

        prefix = key;

        nn = (byte) (v & 0x07);
    }

    /** return base value in readable format. */
    public double baseValue() {
        return Math.pow(10, nn - velocityMap.get(prefix));
    }

    /** return base unit in readable format. */
    public String baseUnit() {
        return (prefix == PREFIX_1KG) ? "kg/h" : "m3/h";
    }

    /* (non-Javadoc)
     * @see java.lang.Object#toString()
     */
    @Override
    public String toString() {
        return String.format("{prefix:%s, nn:%s, baseValue():%s, baseUnit():%s}", prefix, nn, baseValue(), baseUnit());
    }

    /**
     * base unit indicator.
     * 0x38 - 10(nnn-6) m3/h
     * 0x40 - 10(nnn-7) m3/h
     * 0x41 - 10(nnn-9) m3/h
     * 0x50 - 10(nnn-3) kg/h
     * 
     * @return the prefix
     */
    public byte getPrefix() {
        return prefix;
    }

    /**
     * base unit indicator.
     * 0x38 - 10(nnn-6) m3/h
     * 0x40 - 10(nnn-7) m3/h
     * 0x41 - 10(nnn-9) m3/h
     * 0x50 - 10(nnn-3) kg/h
     * 
     * @param key
     *            the prefix to set
     */
    public void setPrefix(byte key) {
        if (!velocityMap.containsKey(key)) {
            throw new IllegalArgumentException("flow unit is invalid.");
        }
        this.prefix = key;
    }

    /**
     * Default to - 0011 1110, 1.0m3/h.
     * base unit indicator.
     * 0x38 - 10(nnn-6) m3/h
     * 0x40 - 10(nnn-7) m3/h
     * 0x41 - 10(nnn-9) m3/h
     * 0x50 - 10(nnn-3) kg/h
     * 
     * @return the n
     */
    public byte getNn() {
        return nn;
    }

    /**
     * Default to - 0011 1110, 1.0m3/h.
     * base unit indicator.
     * 0x38 - 10(nnn-6) m3/h
     * 0x40 - 10(nnn-7) m3/h
     * 0x41 - 10(nnn-9) m3/h
     * 0x50 - 10(nnn-3) kg/h
     * 
     * @param n
     *            the n to set
     */
    public void setNn(byte n) {
        if (n < 0 || n > 7) {
            throw new IllegalArgumentException("n should be [0,7].");
        }

        this.nn = n;
    }

}
